package client.view.maze;

import java.util.Observable;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.MessageBox;

import client.view.Board;
import client.view.MultiKeys;
import client.view.View;

public class GameMazeView extends Observable implements View, Runnable {
	private Board board;
	private Label score;
	private int userCommand;
	private Point startDrag;
	private Point endDrag;
	
	private int[][] currentBoard;
	private int currentScore;
	private String currentMessageTitle;
	private String currentMessageText;
	private int currentMessageStyle;
	private boolean lockedControls;

	public GameMazeView(Board board, int boardRowsSize, int boardColsSize, Label score) {
		this.board = board;
		this.score = score;
		
		board.initBoard(boardRowsSize, boardColsSize, SWT.NONE, mouseAdapter);
		
		initListeners();
	}
	
	@Override
	public int getUserCommand() {
		return userCommand;
	}
	
	@Override
	public void setUserCommand(int userCommand) {
		this.userCommand = userCommand;
		
		setChanged();
		notifyObservers();
	}
	
	@Override
	public void updateDisplay(int[][] data, int score) {
		currentBoard = data;
		currentScore = score;
		board.getDisplay().syncExec(this);
	}
	
	@Override
	public void run() {
		score.setText(" Score:   " + currentScore);
		board.updateBoard(currentBoard);
	}
	
	@Override
	public void setLockControls(boolean lock) {
		lockedControls = lock;
	}
	
	@Override
	public boolean getLockControls() {
		return lockedControls;
	}

	@Override
	public boolean showEndGame(int gameState) {
		currentMessageTitle = "You win";
		currentMessageText = "You win!";
		currentMessageStyle = SWT.ICON_INFORMATION | SWT.OK;
		board.getDisplay().syncExec(showMessage);
		
		return true;	
	}
	
	Runnable showMessage = new Runnable() {
	    @Override
	    public void run() {
	    	MessageBox messageBox = new MessageBox(board.getShell(), currentMessageStyle);
			messageBox.setText(currentMessageTitle);
			messageBox.setMessage(currentMessageText);
			messageBox.open();
	    }
	};
	
	MultiKeys multiKeyListener = new MultiKeys(this);
	private void initListeners() {
		board.addKeyListener(multiKeyListener);
		board.addDisposeListener(new DisposeListener() {
			@Override
			public void widgetDisposed(DisposeEvent arg0) {
				multiKeyListener.dispose();
			}
		});
	}

	MouseAdapter mouseAdapter = new MouseAdapter() {  
        public void mouseDown(MouseEvent e){  
            startDrag = new Point(e.x, e.y);  
        }
        
        public void mouseUp(MouseEvent e) {  
        	endDrag = new Point(e.x, e.y);   
 
        	if (!getLockControls() && startDrag != null && endDrag != null) {
                int deltaX = startDrag.x - endDrag.x;
            	int deltaY = startDrag.y - endDrag.y;
            	
	            if (deltaX>0 && (0.23*deltaX)>Math.abs(deltaY)){
	            	//Move Left
	            	setUserCommand(3);
	            }
	            else if (deltaX<0 && (0.23*Math.abs(deltaX))>Math.abs(deltaY)) {
	            	//Move Right
	            	setUserCommand(4);
	            }
	            else if (deltaY<0 && (0.23*Math.abs(deltaY))>Math.abs(deltaX)) {
	            	//Move Down
	            	setUserCommand(2);
	            }
	            else if (deltaY>0 && (0.23*deltaY)>Math.abs(deltaX)) {
	            	//Move Up
	            	setUserCommand(1);
	            }
	            else if (deltaY>0 && deltaX>0) {
	            	//Move Up and Left (Horizontal)
	            	setUserCommand(6);
	            }
	            else if (deltaY>0 && deltaX<0) {
	            	//Move Up and Right (Horizontal)
	            	setUserCommand(5);
	            }
	            else if (deltaY<0 && deltaX>0) {
	            	//Move Down and Left (Horizontal)
	            	setUserCommand(8);
	            }
	            else if (deltaY<0 && deltaX<0) {
	            	//Move Down and Right (Horizontal)
	            	setUserCommand(7);
	            }
	            else {
	            	setUserCommand(0);
	            }
	            
	            startDrag = null;  
	            endDrag = null;
        	}
        }  
    };
}